/*
 * =============================================================
 *
 *        Project:  apue
 *
 *       Filename:  abort.c
 *
 *         Editor:  vim :set et ts=2 sts=2 sw=2
 *
 *         Author:  Martin Y. Yang , yang@libpix.org
 *
 *    Description:  
 *
 * =============================================================
 */

/**
 * @file
 * @brief Figure 10.25 Implementation of POSIX.1 abort
 */

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void abort1(void)
{
  sigset_t mask;
  struct sigaction action;

  /*
   * Caller can't ignore SIGABRT, if so reset to default
   */
  sigaction(SIGABRT, NULL, &action);
  if (action.sa_handler == SIG_IGN) {
    action.sa_handler = SIG_DFL;
    sigaction(SIGABRT, &action, NULL);
  }
  if (action.sa_handler == SIG_DFL)
    fflush(NULL);                               /* flush all open stdio streams */

  /*
   * Caller can't block SIGABRT; make sure it's unblocked
   */
  sigfillset(&mask);
  sigdelset(&mask, SIGABRT);                    /* mask has only SIGABRT turned off */
  sigprocmask(SIG_SETMASK, &mask, NULL);
  kill(getpid(), SIGABRT);                      /* send the signal */

  /*
   * If we're here, process caught SIGABRT and returned;
   */
  fflush(NULL);                                 /* flush all open stdio streams */
  action.sa_handler = SIG_DFL;
  sigaction(SIGABRT, &action, NULL);            /* reset to default */
  sigprocmask(SIG_SETMASK, &mask, NULL);        /* just in case ... */
  kill(getpid(), SIGABRT);                      /* and one more times */
  exit(1);                                      /* this should never be executed ... */
}


